package com.terminee.activities;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;

import com.terminee.model.ClientTerm;
import com.terminee.threads.BackendThread;
import com.terminee.threads.BackendThread.BackendThreadMessages;
import com.terminee.threads.BackendThread.BackendThreadModes;

public class TermineeLauncher extends Activity {
	
	// different types of dialogs
	static final int SEARCH_PROGRESS_DIALOG = 0;
	static final int NO_TERM_DIALOG = 1;
	static final int TROUBLE_GETTING_RESULTS = 2;
	static final int NO_RESULTS_FOUND = 3;
	
	// view components
	private EditText searchText;
	private ImageButton searchButton;
	private InputMethodManager softKeyboard;
	
	// Define the Handler that receives messages from the search thread and update the progress
    final Handler handler = new Handler() { public void handleMessage(Message msg) { handleBackendThreadMessage(msg);}};
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	    setTitle(R.string.launcher_activity_name);
        setContentView(R.layout.terminee_launcher);
        
        // get view component references
		searchText = (EditText) findViewById(R.id.SearchBox);
		searchButton = (ImageButton) findViewById(R.id.SearchButton);
		
		// get system services
		softKeyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		
		// search text key listener
		searchText.setOnKeyListener(new OnKeyListener() {
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				
				// When Enter is pressed hide softkeyboard, lose focus, and search for term definitions
				if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
					searchForTerm(v);
					return true;
				}
				return false;
			}
		});

		// search text change listener
		searchText.setOnFocusChangeListener(new OnFocusChangeListener() {
			public void onFocusChange(View v, boolean hasFocus) {

				// if gets focus and default search string is there remove it and set text to black
				if (hasFocus && ((EditText) v).getText().toString().
						equalsIgnoreCase(getResources().getString(R.string.search_default))) {
					searchText.setText("", TextView.BufferType.EDITABLE);
					searchText.setTextColor(Color.BLACK);
				}
			}
		});
		
		// start searching when search button is clicked
		searchButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { searchForTerm(v); }});
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.launcher_menu, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.DefineMenuItem:
            addDefinition("");
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
    
    @Override
    protected void onRestoreInstanceState (Bundle savedInstanceState) {
    	super.onRestoreInstanceState(savedInstanceState);
    	
    	// change font to black if not default word, (for orientation changes)
		if(!searchText.getText().toString().
				equalsIgnoreCase(getResources().getString(R.string.search_default))) {
			searchText.setTextColor(Color.BLACK);
		}
    }
    
    /**
     * Search for term
     */
    private void searchForTerm(View v) {
    	searchButton.setClickable(false);
    	softKeyboard.hideSoftInputFromWindow(v.getWindowToken(), 0);
    	
    	if(searchText.getText().toString().length() < 1 || searchText.getTextColors().getDefaultColor() == Color.LTGRAY) {
			showDialog(NO_TERM_DIALOG);
			searchButton.setClickable(true);
			return;
		}
		
		showDialog(SEARCH_PROGRESS_DIALOG);
		searchButton.setClickable(true);
		
		Hashtable<String,Object> extraParams = new Hashtable<String, Object>();
		Uri.Builder uriBuilder = new Uri.Builder();
		uriBuilder = uriBuilder.encodedPath(getResources().getString(R.string.terminee_prod_host) + "resources/terminee/get").
		appendQueryParameter("word", searchText.getText().toString());
		extraParams.put("uriBuilder", uriBuilder);
	    
	    // start up thread 
		BackendThread thread = new BackendThread(handler, BackendThreadModes.RetrieveResults, extraParams);
		thread.start();
    }
    
    private void displaySearchResults(List<ClientTerm> results) {
    	Intent termineeResultsDisplay = new Intent(TermineeLauncher.this, TermineeResultsDisplay.class);
 	   	
    	// extract term and definitions
    	termineeResultsDisplay.putExtra("term", results.get(0).getWord());
    	ArrayList<String> definitions = new ArrayList<String>();
    	for(ClientTerm result : results) {
    		definitions.add(result.getDefinition());
    	}
    	termineeResultsDisplay.putExtra("definitions", definitions);
    	
 	   	startActivity(termineeResultsDisplay);
    }
    
    /**
	 * Handle message return from threads
	 * @param msg Message returned from thread
	 */
	@SuppressWarnings("unchecked")
	private void handleBackendThreadMessage(Message msg) {
		dismissDialog(SEARCH_PROGRESS_DIALOG);
		switch((BackendThreadMessages)msg.getData().getSerializable("message type")) {
		case SearchSuccessful:
			displaySearchResults((List<ClientTerm>)msg.obj);
			break;
		case TroubleGettingResults:
			showDialog(TROUBLE_GETTING_RESULTS);
			break;
		case NoResultsFound:
			showDialog(NO_RESULTS_FOUND);
			break;
		}
	}
	
	/**
	 * Creates dialogs
	 */
	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog = null;
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		switch (id) {
		case SEARCH_PROGRESS_DIALOG:
			ProgressDialog progressDialog = new ProgressDialog(this);
			progressDialog.setMessage("Searching for term. Please wait...");
			progressDialog.setCancelable(false);
			dialog = progressDialog;
			break;
		case NO_TERM_DIALOG:
			// build alert dialog with error message and ok button
			builder.setMessage("You must enter a term to search for.")
		       .setCancelable(false)
		       .setNeutralButton("Ok", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   dismissDialog(NO_TERM_DIALOG);
		           }
		       });
			dialog = builder.create();
			break;
		case TROUBLE_GETTING_RESULTS:
			// build alert dialog with error message and ok button
			builder.setMessage("Trouble getting search results. Please try again")
		       .setCancelable(false)
		       .setNeutralButton("Ok", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   dismissDialog(TROUBLE_GETTING_RESULTS);
		           }
		       });
			dialog = builder.create();
			break;
		case NO_RESULTS_FOUND:
			// build alert dialog with error message and ok button
			builder.setMessage("No definitions found.")
		       .setCancelable(false)
		       .setNeutralButton("Ok", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   dismissDialog(NO_RESULTS_FOUND);
		           }
		       })
		       .setPositiveButton("Define", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   dismissDialog(NO_RESULTS_FOUND);
		        	   addDefinition(searchText.getText().toString());
		           }
		       });
			dialog = builder.create();
			break;
		}

		return dialog;
	}
	
	/**
	 * Add another definition to term
	 * 
	 * @param term term to define will automatically be filled in if provided (optional)
	 */
	public void addDefinition(String term) {
		Intent termineeInput = new Intent(this, TermineeInput.class);
 	   	if(term != null && term.length() > 0)
 	   		termineeInput.putExtra("term", term);
 	   	startActivity(termineeInput);
	}
}